﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NSoup.Nodes;
using Com.Toook.AutoDownloadHtml.SaveData;
using System.Net;
using Com.Toook.AutoDownloadHtml.Entity;
using System.Collections.Specialized;
using Com.Toook.AutoDownloadHtml.Util;

namespace Com.Toook.AutoDownloadHtml.DownloadHtml
{
    public abstract class NewsAbstract
    {/// <summary>
        /// 开始按步骤下载分类中的新闻
        /// </summary>
        public void DownloadNews()
        {
            //1、获取新闻分类Document
            this.docCategory = GetDocument(this.urlCategory);
            if(this.docCategory == null)
            {
                return;//下载html失败
            }
            if(this.sdNewsUrls != null)
            {
                this.sdNewsUrls.Clear();// 如果不为null，清空内容
            }
            //2、获取每个新闻url (保存在this.sdNewsUrls字典中)
            this.GetNewsUrls();

            //3、遍历 2中 this.sdNewsUrls中的url, 获取分类中的所有新闻内容 (保存在this.news 新闻对象中)
            this.GetEachNewsAndSave();

        }
        /// <summary>
        /// 默认构造函数，新闻分类url在各个子类中指定
        /// </summary>
        public NewsAbstract()
        {
        }
        /// <summary>
        /// 根据新闻分类url抓取分类中的每个新闻内容
        /// </summary>
        /// <param name="url">新闻分类url</param>
        public NewsAbstract(string url)
        {
            this.urlCategory = url;
        }
        /// <summary>
        /// 根据新闻分类url抓取分类中的每个新闻内容
        /// </summary>
        /// <param name="url">新闻分类url</param>
        /// <param name="charset">页面编码</param>
        public NewsAbstract(string url, string charset)
        {
            this.urlCategory = url;
            if(string.IsNullOrEmpty(charset))
            {
                this.charset = charset;
            }
        }
        /// <summary>
        /// 获取每个分类页面中的新闻url列表(如国内新闻中的每条新闻url)
        /// 保存结果到this.sdNewsUrls 字典StringDictionary
        /// </summary>       
        protected abstract void GetNewsUrls();
        /// <summary>
        /// 1、获取this.sdNewsUrls中的每个新闻内容,并解析为this.news
        /// 2、调用SaveNewsContent()保存到数据库
        /// </summary>        
        protected abstract void GetEachNewsAndSave();

        #region 子类调用的公共方法
        /// <summary>
        /// 保存新闻对象(this.news)到数据库。如果存在相同url,返回false
        /// </summary>
        /// <returns>如果存在相同url,返回false</returns>
        protected bool SaveNewsContent()
        {
            return NewsSqlite.SaveNews(this.news);
        }
        #endregion 子类调用的公共方法

        /// <summary>
        /// 获取指定页面的Document对象
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        protected Document GetDocument(string url)
        {
            Document docment = null;
            if(string.IsNullOrEmpty(this.charset))
            {
                docment = this.DownloadDocument(url);
            }
            else
            {
                docment = this.DownloadDocument(url, this.charset);
            }
            return docment;
        }
        /// <summary>
        /// 根据url获取NSoup.Nodes.Document
        /// </summary>
        /// <param name="url"></param>
        private Document DownloadDocument(string url)
        {
            Document docment = null;
            try
            {
                docment = NSoup.NSoupClient.Connect(url).Get();
            }
            catch(Exception e)
            {
                LogHelper.Log.Error("NSoup.NSoupClient.Connect(url).Get() error. url=" + url, e);
            }
            return docment;
        }
        /// <summary>
        /// 根据url和指定编码 获取NSoup.Nodes.Document
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="encode">html编码 charset</param>
        private Document DownloadDocument(string url, string encode)
        {
            byte[] byteHtml = null;
            Document docment = null;
            try
            {
                byteHtml = new WebClient().DownloadData(url);
                string html = Encoding.ASCII.GetString(byteHtml);
                docment = NSoup.NSoupClient.Parse(html);
            }
            catch(WebException webEx)
            {
                LogHelper.Log.Error("WebClient().DownloadData(url) error. url=" + url + ", encode=" + encode, webEx);
            }
            return docment;
        }

        /// <summary>
        /// 保存新闻对象
        /// </summary>
        protected News news;
        /// <summary>
        /// 分类页面url. 如 sohu.com/world.shtml
        /// </summary>
        protected string urlCategory;
        /// <summary>
        /// 分类页面编码
        /// </summary>
        protected string charset;
        /// <summary>
        /// 分类html页面Document
        /// </summary>
        protected Document docCategory;
        /// <summary>
        /// 分类中所有新闻url 字典
        /// </summary>
        protected StringDictionary sdNewsUrls;
    }
}
